// RealPlay Ltd  copyrights.
// This program is Open Source AsIs
// You may use it for all purposes, including commercial
// But!!!
// If you use any part of this code, you must state clearly
// both in your source file and in the Help|about of your program,
// that the origin program or code was built by RealPlay Ltd

// ***********************************************************************/
// *                                                                     */
// *        This file is the Real Play (Animation) unit of "Paint" Program  */
// *                                                                     */
// ***********************************************************************/

unit UPRealLayers;

interface

uses Windows, Dialogs, Forms, Classes, Graphics, SysUtils, ExtCtrls, XMLIntf,
  Menus,
  MPlayer,
  UP_XML;

type
  TBMLayer = Class(Tbitmap)
  public
    FileName: string;
    Time: integer; // in mili sec
    // TransparentColor:TColor;
  end;

  TOList = class(tlist)
  public
    function GetItem(Index: integer): TBMLayer;
    procedure SetItem(Index: integer; Value: TBMLayer);
    property Items[Index: integer]: TBMLayer read GetItem write SetItem;
    default;
  end;

  TBMLList = class(TOList)
  public
    position: integer;
    Timer: TTimer;
    procedure OnTimer(Sender: TObject);

    procedure PlayAct(Button: TMPBtnType);
    procedure getlistfromXML(path: string);
    procedure MakeMenu;
    Constructor create;
    destructor Destroy; override;
  end;

implementation

uses UPMain, UPUtil, UPMenu;

Constructor TBMLList.create;
begin
  inherited create;
  position := 0;
  Timer := TTimer.create(FPaint);
  Timer.Enabled := false;
  Timer.Interval := 1;
  Timer.OnTimer := self.OnTimer;
end;

destructor TBMLList.Destroy;
begin
  while count > 0 do
  begin
    Items[0].Free;
    delete(0);
  end;
  inherited Destroy;
end;

var
  updir: boolean = true;

  // --------------------------------------------------------------
procedure TBMLList.OnTimer(Sender: TObject);

begin
  if count > 0 then
  begin
    AssBMP(Items[position], FPaint.FWA.Im);
    if Items[position].Time <> 0 then
      Timer.Interval := Items[position].Time
    else
      Timer.Interval := 100;
    if updir then
      inc(position)
    else
      dec(position);
    if position >= count then
    begin
      position := count - 1;
      updir := not updir;
    end;
    if position < 0 then
    begin
      position := 0;
      updir := not updir;
    end;
  end;
end;

procedure TBMLList.PlayAct(Button: TMPBtnType);
var
  proc_info: TProcessInformation;
  startinfo: TStartupInfo;
  ExitCode: longword;
  StExe: string;
begin
  FPaint.FrRTool1.MP.EnabledButtons := [btplay .. btRecord];
  with FPaint do
    with FWA do
      with FrRTool1 do
        case Button of
          btplay:
            begin
              MP.EnabledButtons := [btPause .. btback];
              MP.VisibleButtons := MP.VisibleButtons - [btplay] + [btPause];
              Items[self.position].Assign(FPaint.FWA.Im.Picture.Bitmap);
              AniList.Timer.Enabled := true;
            end;
          btPause:
            begin
              MP.EnabledButtons := [btplay .. btRecord] - [btPause];
              MP.VisibleButtons := MP.VisibleButtons + [btplay] - [btPause];
              AniList.Timer.Enabled := false;
              MyStat.Changed := MyStat.Changed;
            end;
          btstop, btprev:
            begin
              MP.EnabledButtons := [btplay .. btRecord] - [btPause, btstop,
                btprev];
              MP.VisibleButtons := MP.VisibleButtons + [btplay] - [btPause];
              AniList.Timer.Enabled := false;
              Items[self.position].Assign(FPaint.FWA.Im.Picture.Bitmap);
              self.position := 0;
              AssBMP(Items[self.position], Im);
              MyStat.Changed := MyStat.Changed;
            end;
          btNext:
            begin
              MP.EnabledButtons := [btplay .. btRecord] - [btPause, btNext];
              MP.VisibleButtons := MP.VisibleButtons + [btplay] - [btPause];
              AniList.Timer.Enabled := false;
              Items[self.position].Assign(FPaint.FWA.Im.Picture.Bitmap);
              self.position := count - 1;
              AssBMP(Items[self.position], Im);
              MyStat.Changed := MyStat.Changed;
            end;
          btstep:
            begin
              MP.EnabledButtons := [btplay .. btRecord] - [btPause];
              MP.VisibleButtons := MP.VisibleButtons + [btplay] - [btPause];
              AniList.Timer.Enabled := false;
              Items[self.position].Assign(FPaint.FWA.Im.Picture.Bitmap);
              inc(self.position);
              if self.position >= count then
                self.position := count - 1;
              AssBMP(Items[self.position], Im);
              MyStat.Changed := MyStat.Changed;
            end;
          btback:
            begin
              MP.EnabledButtons := [btplay .. btRecord] - [btPause];
              MP.VisibleButtons := MP.VisibleButtons + [btplay] - [btPause];
              AniList.Timer.Enabled := false;
              dec(self.position);
              if self.position < 0 then
                self.position := 0;
              AssBMP(Items[self.position], Im);
              MyStat.Changed := MyStat.Changed;
            end;
          btRecord:
            begin
              Items[self.position].Assign(FPaint.FWA.Im.Picture.Bitmap);
              // Initialize the structures
              FillChar(proc_info, sizeof(TProcessInformation), 0);
              FillChar(startinfo, sizeof(TStartupInfo), 0);
              startinfo.cb := sizeof(TStartupInfo);
              StExe := extractfilepath(FMenu.opd1.FileName);
              system.delete(StExe, length(StExe), 1);
              StExe := extractfilepath(paramstr(0)) + 'GrabPc2V.exe ' + StExe;
              // 'c:\windows\notepad.exe';
              // Attempts to create the process
              if CreateProcess(nil, pchar(StExe), nil, nil, false,
                NORMAL_PRIORITY_CLASS, nil, nil, startinfo, proc_info)
                <> false then
              begin
                // The process has been successfully created
                // Now let's wait till it ends...
                FPaint.Hide;
                WaitForSingleObject(proc_info.hProcess, INFINITE);
                // Process has finished. Now we should close it.
                GetExitCodeProcess(proc_info.hProcess, ExitCode); // Optional
                CloseHandle(proc_info.hThread);
                CloseHandle(proc_info.hProcess);
                FPaint.Show;
              end
              else
                // Failure creating the process
                MessageDlg('Couldn''t execute the Record operation', mtError,
                  [mbOk], 0);
            end; // btRecord
        end; // Case Button
end;

procedure TBMLList.getlistfromXML(path: string);
var
  lay: TBMLayer;
  iNode: IXMLNode;
  fname, ftime, fTrans: string;
begin
  iNode := FXML.XMLDoc.DocumentElement; // .ChildNodes.First;
  if iNode <> nil then
    iNode := iNode.ChildNodes.FindNode('Images');
  if iNode <> nil then
    iNode := iNode.ChildNodes.FindNode('BackgroundImage');
  while iNode <> nil do
  begin
    fname := iNode.Attributes['FileName'];
    if (fname <> '') and fileExists(path + fname) then
    begin
      lay := TBMLayer.create;
      lay.FileName := fname;
      lay.LoadFromFile(path + fname);
      ftime := iNode.Attributes['Time'];
      if ftime <> '' then
        lay.Time := trunc(1000 * strtofloat(ftime));
      fTrans := iNode.Attributes['TransparentColor'];
      if fTrans <> '' then
        lay.TransparentColor := strtoint(fTrans)
      else
        lay.TransparentColor := $FFFEFF;
      self.Add(lay);
    end;
    repeat
      iNode := iNode.NextSibling;
    until (iNode = nil) or (iNode.LocalName = 'BackgroundImage');
  end;
end;

procedure TBMLList.MakeMenu;
var
  mm: TMainMenu;
  mi: TmenuItem;
  i, nu: integer;
  step: real;
begin
  if count <= 9 then
  begin
    step := 1;
    nu := count - 1;
  end
  else
  begin
    step := (count - 1) / 8;
    nu := 8;
  end;
  if count > 0 then
  begin
    mm := FPaint.Menu;
    FPaint.Menu := nil;
    mi := TmenuItem.create(FPaint);
    mi.Caption := '-';
    UPMenu.FMenu.MenuRAni.Add(mi);
    for i := 0 to nu do
    begin
      mi := TmenuItem.create(FPaint);
      mi.Caption := '&' + inttostr(i + 1) + ' ' + Items[Round(step * i)]
        .FileName;
      UPMenu.FMenu.MenuRAni.Add(mi);
      mi.OnClick := UPMenu.FMenu.MenuFileClick;
    end;

    FPaint.Menu := mm;
  end;
  FPaint.FrRTool1.MP.EnabledButtons := [btplay .. btRecord] - [btPause, btstop];
end;

// -------------------------------------------------
function TOList.GetItem(Index: integer): TBMLayer;
begin
  result := list[index];
end;

procedure TOList.SetItem(Index: integer; Value: TBMLayer);
begin
  list[index] := Value;
end;

end.
